<template>
  <div class="import-by-department">
    <je-modal
      v-model:visible="visible1"
      title="人员规划"
      button-align="center"
      width="1142"
      height="720"
      cancel-button
      :ok-button="onSubmit"
      :resize="false"
      @close="closeDialog"
    >
      <div class="content">
        <div class="construction">
          <je-panel v-bind="options">
            <je-panel-item region="top" v-bind="options.top">组织结构</je-panel-item>
            <je-panel-item>
              <je-tree
                ref="treeview"
                class="table-treeView"
                :draggable="{
                  group: { name: 'group', pull: 'clone', put: false },
                  sort: false,
                }"
                :search="{ subLabelField: 'bean.DEPARTMENT_NAME' }"
                :tree-config="{
                  // expandAll: true,
                  trigger: 'cell-dblclick',
                  rowField: 'id',
                  parentField: 'parent',
                }"
                :loading="loading"
                size="mini"
                :data="treeData"
                @drop="drop"
                @before-drop="beforedrop"
              >
              </je-tree>
            </je-panel-item>
            <je-panel-item region="bottom" v-bind="options.bottom"> </je-panel-item>
          </je-panel>
          <div class="bottom">
            <div class="tip"> 把人员直接拖拽到右侧板块中完成选择 </div>
          </div>
        </div>
        <div class="is-select">
          <je-panel v-bind="options1">
            <je-panel-item region="top" v-bind="options1.top">已选人员</je-panel-item>
            <je-panel-item>
              <je-search
                v-model:value="value"
                label-field="text"
                @search="onSearch"
                @select="onSelect"
              ></je-search>
              <div id="import-draggable" class="my-draggable">
                <template v-if="isSelect && isSelect[0]">
                  <div
                    v-for="element in isSelect"
                    :key="'list-' + element?.id"
                    class="draggabled"
                    :class="{ active: element.id === currentId }"
                    @click="itemClickEvent(element)"
                  >
                    <div
                      ><i class="fal fa-user-alt my-drag-item"></i>&nbsp;&nbsp;{{
                        element.bean.USER_NAME
                      }}（{{ element.bean.DEPARTMENT_NAME }}）</div
                    >
                    <div v-show="element.id === currentId" @click.stop="removeone(element)"
                      ><i class="fal fa-times"></i
                    ></div>
                  </div>
                </template>
                <div v-else-if="!loading && isSelect.length === 0" class="word">暂无数据</div>
                <je-loading v-if="loading"></je-loading>
              </div>
            </je-panel-item>
            <je-panel-item region="bottom"> </je-panel-item>
          </je-panel>
          <div class="btn">
            <je-button type="text" style="color: #b8741a" @click="removeAll"
              >移除全部</je-button
            ></div
          >
          <div id="msg"></div>
        </div>
        <div class="structure">
          <je-panel v-bind="options">
            <je-panel-item region="top" v-bind="options.top">结构展示</je-panel-item>
            <je-panel-item>
              <je-tree
                ref="treeview1"
                class="table-treeView1"
                :search="{ subLabelField: 'bean.DEPARTMENT_NAME' }"
                :tree-config="{
                  trigger: 'cell-dblclick',
                  rowField: 'id',
                  parentField: 'parent',
                }"
                :loading="loading"
                size="mini"
                :data="treeData1"
              >
                <template #nodeDefault="{ row }">
                  <div
                    >{{ row.text }}
                    <i
                      v-show="row.children.length === 0 && row.id === currentId"
                      class="fal fa-times my-icon"
                      @click.stop="removeone(row)"
                    ></i
                  ></div>
                </template>
              </je-tree>
            </je-panel-item>
            <je-panel-item region="bottom" v-bind="options.bottomRight"> </je-panel-item>
          </je-panel>
          <div class="bottom-text">
            <je-button type="text" style="color: #b8741a" @click="removeAll"
              >移除全部</je-button
            ></div
          >
        </div>
      </div>
    </je-modal>
  </div>
</template>

<script>
  import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';

  import { Panel, Tree, Modal, Search, Button, Loading } from '@jecloud/ui';

  import Sortable from 'sortablejs';

  import _ from 'lodash';

  import { pinyin } from '@jecloud/utils';

  import { importByDepartmentUsersApi, loadDepartmentTreeUserApi, loadRoleUserApi } from '@/api';

  export default defineComponent({
    name: 'ImportByDepartment',
    components: {
      JePanel: Panel,
      JePanelItem: Panel.Item,
      JeTree: Tree,
      // JeMenu: Menu,
      // JeMenuItem: Menu.Item,
      JeModal: Modal,
      JeSearch: Search,
      JeButton: Button,
      JeLoading: Loading,
    },
    props: {
      visible: {
        type: Boolean,
        default: false,
      },
      roleIds: {
        type: String,
        default: '',
      },
    },
    emits: ['update:visible', 'loadAccountEvent'],
    setup(props, { emit }) {
      // 自己关闭对话框，修改父组件数据状态
      let closeFlag = false;
      const closeDialog = () => {
        if (closeFlag) {
          emit('loadAccountEvent');
        }
        setTimeout(() => {
          emit('update:visible', false);
        }, 1000);
      };
      const visible1 = ref(props.visible);

      const treeData = ref([]);
      const loading = ref(false);
      // 左和中的配置
      const options = reactive({
        top: {
          size: 40,
          style: {
            background: '#F7F9FC',
            borderTop: 'none',
            textAlign: 'center',
            lineHeight: '41px',
            borderBottom: '0',
            borderLeft: '1px solid #e6e6e6',
            borderRight: '1px solid #e6e6e6',
          },
        },
        bottom: {
          size: 60,
          style: {
            borderRight: '1px solid #e6e6e6',
          },
        },
        bottomRight: {
          size: 60,
          style: {
            borderLeft: '1px solid #e6e6e6',
            borderRight: '1px solid #e6e6e6',
          },
        },
      });
      // 右的配置
      const options1 = reactive({
        top: {
          size: 40,
          style: {
            background: '#F7F9FC',
            borderBottom: 'none',
            borderTop: 'none',
            textAlign: 'center',
            lineHeight: '40px',
          },
        },
        bottom: {
          size: 60,
          style: {
            borderLeft: '1px solid #e6e6e6',
          },
        },
      });

      // 获取部门人员数据
      let myDataRes = ref([]);
      const treeview1 = ref('treeview1');
      // 当前id用于高亮和显示x
      const currentId = ref(null);
      // 右侧tree数据
      const treeData1 = ref([]);
      // 得到左侧tree数据
      const getTreeData = () => {
        loading.value = true;
        loadDepartmentTreeUserApi().then((res) => {
          const result = res.children;
          treeData.value = _.cloneDeep(result);
          myDataRes.value = _.cloneDeep(result);
          loading.value = false;
          // 加载中间区域数据
          loadRoleUser();
          // 默认展开第一层
          nextTick(() => {
            res.children.forEach((row) => {
              treeview.value.setTreeExpand(row, true);
            });
          });
        });
      };

      // 中间的已选人员
      const isSelect = ref([]);
      // 角色ID集合
      let roleIds = null;
      // 获取中间人员数据回显
      let meta = []; // 对比项
      const treeview = ref('treeview');
      const loadRoleUser = () => {
        loading.value = true;
        loadRoleUserApi({ roleIds }).then((res) => {
          const result = [];
          const response = res;
          response.map((item) => {
            const row = treeview.value.getRowById(item.JE_RBAC_DEPTUSER_ID);
            result.push(row);
          });
          isSelect.value = result; // 赋值
          meta = _.cloneDeep(result); // 对照组赋值
          loading.value = false;
          if (!isSelect.value[0]) return false;
          // 加载右侧树
          getRightTree();
        });
      };

      // 中间的拖动列
      // eslint-disable-next-line no-unused-vars
      let mySortable = null;
      onMounted(() => {
        getTreeData();
        initData();
      });

      // 初始化数据及拖动组
      const initData = () => {
        roleIds = props.roleIds;
        // 渲染和配置
        setTimeout(() => {
          let importDraggable = document.getElementById('import-draggable');
          let ops2 = {
            animation: 300,
            delay: 0,
            sort: true,
            forceFallback: true, // 不使用H5原生拖动
            group: { name: 'group' }, // 拖动组
            onAdd: dropAdd,
            onUpdate: sortEvent,
          };
          mySortable = Sortable.create(importDraggable, ops2);
        }, 0);
      };

      // 排序事件
      const sortEvent = (e) => {
        // 修改位置的数据
        const temp = isSelect.value[e.oldIndex];
        // 数组原位置删掉此条数据
        isSelect.value.splice(e.oldIndex, 1);
        // 数组新位置增加此条数据
        isSelect.value.splice(e.newIndex, 0, temp);
      };

      // 拖动时
      const beforedrop = ({ target }) => {
        return target?.text !== '节点2';
      };
      // 拖动排序
      let _index = null;
      // 数据有增加时
      const dropAdd = (e) => {
        _index = e.newDraggableIndex;
      };
      // 拖动结束
      let midlist = []; // 拖动后给中间数组赋值数组
      // 拖动结束
      const drop = (row) => {
        // 拖动的是节点还是枝干
        if (row.row.children.length === 0) {
          // 判断重复
          const isTrue = isSelect.value.some((item) => {
            return item.id === row.row.id;
          });
          // 不存在则合并数据，并添加
          if (!isTrue && row.row.nodeInfoType === 'user') {
            isSelect.value.splice(_index, 0, row.row);
            getRightTree();
          }
        } else {
          // 两相同数组去重
          const arr = [];
          isSelect.value.map((td) => {
            arr.push(td.id);
          });
          // midlist = row.row.children.filter((item) => {
          //   return !arr.includes(item.id) && item.nodeInfoType === 'user';
          // });
          dropItems(row.row, arr);
          // 反转数组
          midlist = midlist.reverse();
          // 遍历追加
          midlist.map((item) => {
            isSelect.value.splice(_index, 0, item);
          });
          getRightTree();
        }
      };
      // 递归拖入
      const dropItems = (items, arr) => {
        items.children.forEach((item) => {
          if (!arr.includes(item.id) && item.nodeInfoType === 'user') {
            midlist.push(item);
          }
          if (item.children?.length > 0) {
            dropItems(item, arr);
          }
        });
      };

      // 初始化右侧tree
      let childList = []; // 一级子菜单组
      // 得到右侧tree
      const getRightTree = () => {
        treeData1.value = _.cloneDeep(myDataRes.value);
        isSelect.value.find((item) => {
          setTimeout(() => {
            // 展开
            expandParent(item, 'noCascade');
            // 获取数据
            getItemByRecursion(item);
            // console.log(getItemByRecursion(item), 'res');
          });
        }, 0);
        setTimeout(() => {
          // 去重
          childList = Array.from(new Set(childList));
          // 获取右侧树数据
          treeData1.value = treeData1.value.filter((item) => {
            return childList.includes(item.id);
          });
          childList = [];
        }, 0);
      };
      let arr = [];
      // 已选人员选项点击事件：显示右侧树
      const itemClickEvent = async (row) => {
        currentId.value = row.id;
        // 通过row高亮左侧树和右侧树某一行
        setTimeout(() => {
          expandParent(row);
          treeview.value.setCurrentRow(row);
          treeview1.value.setCurrentRow(row);
        }, 0);
      };

      // 递归遍历得到展开项
      const expandParent = (row, type) => {
        if (row?.parent !== 'ROOT') {
          treeview1.value.setTreeExpand(treeview1.value.getParentRow(row), true);
          expandParent(treeview1.value.getParentRow(row), type);
          if (type != 'noCascade') {
            treeview.value.setTreeExpand(treeview1.value.getParentRow(row), true);
            expandParent(treeview.value.getParentRow(row), type);
          }
        }
      };
      // 递归得到右侧tree数据
      const getItemByRecursion = (row) => {
        // 得到父节点
        let res = treeview1.value.getParentRow(row);
        // 得到中间区域数据的row数组
        let arrayData = currentRowlist();
        // 去重并转化为真数组
        arrayData = Array.from(new Set(arrayData));
        // 存在父节点
        if (res) {
          // 只显示中间区域存在数据
          res.children = res.children.filter((item) => {
            return arrayData.includes(item.id);
          });
          getItemByRecursion(res);
        } else {
          // 不存在父节点直接添加
          childList.push(row.id);
          res = row;
        }
        return res;
      };
      // 通过isSelect得到row的数组
      let arrRow = [];
      const currentRowlist = () => {
        arrRow = [];
        isSelect.value.find((item) => {
          arrRow.push(item.id);
          getParentRowByRow(item);
        });
        return arrRow;
      };
      // 得到所有的row
      const getParentRowByRow = (row) => {
        let myRow = treeview.value.getRowById(row.id);
        let res = treeview.value.getParentRow(myRow);
        if (res?.parent !== 'ROOT') {
          arrRow.push(res.id);
          getParentRowByRow(res);
        }
      };

      // 移除全部
      const removeAll = () => {
        if (isSelect.value.length === 0) return false;
        Modal.confirm('您确定要移除全部吗？', () => {
          // 清空数据
          closeFlag = true;
          isSelect.value = [];
          treeData1.value = [];
          arr = [];
          midlist = [];
          // childList = [];
          // });
        });
      };
      // 移除一项
      const removeone = (row) => {
        closeFlag = true;
        isSelect.value = isSelect.value.filter((item) => {
          return item.id !== row.id;
        });
        midlist = midlist.filter((item) => {
          return item.id !== row.id;
        });
        arr = arr.filter((item) => {
          return item !== getItemByRecursion(row);
        });
        treeData1.value = treeData1.value.filter((item) => {
          return item !== getItemByRecursion(row);
        });
        if (isSelect.value.length === 0) {
          treeData1.value = [];
        }
        // treeview1.value.reloadData(treeData1.value);
        // treeview1.value.updateData();
        currentId.value = null;
      };

      // 按部门导入请求
      const onSubmit = () => {
        // 对照组
        const arr1 = [];
        meta.map((item) => {
          arr1.push(item.id);
        });
        const arr2 = [];
        isSelect.value.map((item) => {
          arr2.push(item.id);
        });
        // 删除id数组
        let deleteStrArr = arr1.filter((item) => {
          return !arr2.includes(item);
        });
        // 删除项
        let deleteStrData = null;
        if (deleteStrArr.length > 0) {
          deleteStrData = [];
          deleteStrArr.map((item) => {
            const row = treeview.value.getRowById(item);
            deleteStrData.push({
              departmentId: row.bean.JE_RBAC_DEPARTMENT_ID,
              userIds: row.bean.JE_RBAC_USER_ID,
            });
          });
          deleteStrData = JSON.stringify(deleteStrData);
        }
        // // 增加id数组
        // let addStrArr = arr2.filter((item) => {
        //   return !arr1.includes(item);
        // });
        // 增加项
        let addStrData = null;
        if (!isChange()) {
          addStrData = [];
          isSelect.value.map((item, index) => {
            const row = treeview.value.getRowById(item.id);
            addStrData.push({
              departmentId: row.bean.JE_RBAC_DEPARTMENT_ID,
              userIds: row.bean.JE_RBAC_USER_ID,
              sysOrderIndex: index,
            });
          });
          addStrData = JSON.stringify(addStrData);
        }
        if (!isChange()) {
          closeFlag = true;
          importByDepartmentUsersApi({ roleId: roleIds, deleteStrData, addStrData }).then((res) => {
            Modal.notice(res, 'success');
          });
        }
      };
      // 是否变化
      const isChange = () => {
        const bool1 = isSelect.value.every((item, index) => {
          const val1 = isSelect.value[index].id;
          const val2 = meta[index]?.id;
          return val1 === val2;
        });
        const bool2 = meta.every((item, index) => {
          const val1 = isSelect.value[index]?.id;
          const val2 = meta[index].id;
          return val1 === val2;
        });
        const isSort = bool1 && bool2;
        return isSort;
      };

      // 中间 搜索功能
      const value = ref('');
      const onSelect = (val, option) => {
        value.value = val;
        itemClickEvent(option.row);
        // 搜索的事件分发，传相应的item
      };
      // 节点过滤函数
      const filter = (item, keyword) => {
        const _word = item.text?.toLocaleLowerCase() ?? '';
        const pinyinText = pinyin(_word, 'pinyin');
        if (_word.includes(keyword) || pinyinText.includes(keyword)) {
          return true;
        }
        return false;
      };
      // 查询关键字
      const onSearch = (keyword, resolve) => {
        if (isSelect.value.length === 0) return false;
        let items = [];
        keyword = keyword.toLocaleLowerCase();
        isSelect.value.forEach((item) => {
          if (filter(item, keyword)) {
            items.push({
              value: item.text,
              text: item.text,
              key: item.id,
              row: item,
            });
          }
        });
        resolve(items);
      };

      return {
        drop,
        visible1,
        closeDialog,
        onSubmit,
        treeData,
        loading,
        options,
        isSelect,
        treeData1,
        itemClickEvent,
        currentId,
        treeview,
        treeview1,
        removeAll,
        removeone,
        beforedrop,
        onSelect,
        onSearch,
        value,
        options1,
      };
    },
  });
</script>

<style lang="less" scoped>
  .import-by-department {
    :deep(.je-panel-item-region-default) {
      top: 0px !important;
      &::-webkit-scrollbar {
        display: none;
      }
    }
    :deep(.table-treeView .je-panel-item-region-default) {
      top: 40px !important;
    }
    :deep(.table-treeView1 .je-panel-item-region-default) {
      top: 40px !important;
    }
    :deep(.je-panel-item .je-panel-item-region-top) {
      border: none !important;
    }
    .my-icon {
      position: absolute;
      right: 15px;
      top: 5px;
    }
    .active {
      color: @primary-color;
      background-color: @primary-2;
    }
    .content {
      // margin-left: 20px;
      width: 1080px;
      display: flex;
      height: 99%;
    }
    .construction {
      border: 1px solid #e6e6e6;
      border-left: none;
      border-right: none;
      position: relative;
      margin: 0 -1px -1px 0;
      width: 360px;
      height: 100%;
      :deep(.vxe-body--row.is--draggable) {
        &:hover {
          background: @primary-2;
        }
      }
      :deep(.je-panel-item.je-panel-item-region-bottom) {
        border-left: 1px solid #e6e6e6;
      }
    }
    :deep(.ant-input-affix-wrapper-focused.ant-select-selection-search-input) {
      border: 1px solid #5c8dff;
    }
    .is-select {
      position: relative;
      border: 1px solid #e6e6e6;
      margin: 0 -1px -1px 0;
      width: 360px;
      height: 100%;
      :deep(.ant-input-affix-wrapper.ant-select-selection-search-input) {
        border-left: 1px solid #ffffff;
        border-right: 1px solid #ffffff;
        &:hover {
          border: 1px solid #5c8dff;
        }
      }
      :deep(.ant-input-affix-wrapper-focused.ant-select-selection-search-input) {
        border: 1px solid #5c8dff;
      }

      :deep(.je-search) {
        width: 358px;
        position: fixed;
        height: 40px;
        z-index: 99999;
      }
      .my-draggable {
        position: relative;
        padding-top: 40px;
        height: 100%;
        :deep(.vxe-cell) {
          width: 329px !important;
        }
        :deep(.vxe-cell--tree-node) {
          padding-left: 0px !important;
        }
        :deep(.draggabled) {
          height: 32px;
          width: 358px;
          line-height: 30px;
          padding: 0 20px;
          display: flex;
          justify-content: space-between;
          &:hover {
            background: @primary-2;
            cursor: pointer;
          }
        }
        .word {
          position: absolute;
          font-size: 14px;
          top: 44%;
          left: 50%;
          padding-top: 40px;
          transform: translate(-50%, -50%);
        }
        :deep(.je-tree-node-icon) {
          margin: 0px 8px 0 20px;
          font-size: 17px;
        }
        :deep(.vxe-tree--node-btn) {
          display: none;
        }
      }
    }
    .structure {
      // margin: 0 -1px -1px 0;
      border: 1px solid #e6e6e6;
      border-left: none;
      border-right: none;
      position: relative;
      width: 360px;
      height: 100%;
    }
    .btn {
      position: absolute;
      z-index: 999;
      bottom: 10px;
      right: 10px;
    }
    .bottom {
      position: absolute;
      bottom: 10px;
      right: 20px;
    }
    .bottom-text {
      position: absolute;
      bottom: 10px;
      right: 10px;
    }
    .tip {
      position: absolute;
      bottom: 0px;
      right: -10px;
      text-align: center;
      line-height: 30px;
      border: 1px solid #abd09d;
      background: #eff9f2;
      color: #36761f;
      height: 30px;
      width: 338px;
    }
    :deep(.je-tree-search-wrapper > *) {
      height: 40px;
      .ant-input-clear-icon {
        top: 10px;
      }
    }

    :deep(.fa-window-maximize) {
      display: none;
    }
    /*定义要拖拽元素的样式*/
    .ghostClass {
      background-color: @primary-2 !important;
    }

    .chosenClass {
      background-color: @primary-2 !important;
      opacity: 1 !important;
    }

    .dragClass {
      background-color: @primary-2 !important;
      opacity: 1 !important;
      box-shadow: none !important;
      outline: none !important;
      background-image: none !important;
    }
    :deep(.je-panel-item .je-panel-item-region-default) {
      border-left: 1px solid #e6e6e6;
      border-right: 1px solid #e6e6e6;
    }

    .itxst {
      margin: 10px;
    }

    .title {
      padding: 6px 12px;
    }

    .col {
      width: 40%;
      flex: 1;
      padding: 10px;
      border: solid 1px #eee;
      border-radius: 5px;
      float: left;
    }

    .col + .col {
      margin-left: 10px;
    }
    .item {
      padding: 6px 12px;
      margin: 0px 10px 0px 10px;
      border: solid 1px #eee;
      background-color: #f1f1f1;
    }

    .item:hover {
      background-color: #fdfdfd;
      cursor: move;
    }

    .item + .item {
      border-top: none;
      margin-top: 6px;
    }
  }
</style>
